Many modern data processing systems are of the microprocessor-based type, in that the central processing unit (CPU) of the system is a single-chip microprocessor. Particularly with constant increases in the density of active elements within a single integrated circuit, modern microprocessors are synchronous devices operating at very fast clock rates, exceeding 150 MHz. As is known in the art, many other integrated circuits and subsystems in the microprocessor-based digital system cannot operate at the same high speed as the microprocessor. In addition, conventional systems typically communicate digital signals among its circuits and subsystems by way of buses (i.e., groups of parallel conductors) synchronously with a clock signal that is often several times slower than the high speed clock operating the core of the microprocessor CPU.
System performance has been increased in recent years by the increasing use of cache memories that are placed on-chip with the microprocessor, allowing a large fraction of the memory accesses that are performed in the execution of a computer program to take place at the high clock speed available internally within the microprocessor. Of course, the size of on-chip cache memory cannot approach the total system need for random-access memory, requiring system main memory to reside off-chip, typically in slow (relative to the CPU core clock) dynamic random access memory (DRAM). The microprocessor CPU must thus have functionality for performing memory accesses to main memory via a bus.
In addition to on-chip cache memory, one or more units of on-chip memory elements are functionally located between off-chip main memory and the on-chip caches. The function of these memory units is to buffer, or hold, incoming and outgoing information to allow the microprocessor to continue processing during the servicing of a read or write request on the external bus. A write buffer is typically a buffer contained within the bus interface unit (BIU) of the microprocessor, to which data is written from an internal bus within the microprocessor synchronously with the high-speed internal core clock. The write buffer stores this data (along with a tag corresponding to the destination memory address) and presents it to the external bus of the system synchronously with the slower bus clock when the bus and main memory become available; write buffers are also typically used in connection with memory-mapped output functions. Depending, of course, upon the quantity of data being written to main memory, the use of write buffers can greatly improve microprocessor performance. For example, the core of the microprocessor can rapidly write the results of its operations to the write buffer and then continue with the execution of the next instruction, without waiting for the data to be written to and acknowledged by off-chip memory. Write buffers are especially useful in connection with internal cache operation, particularly caches of the write-through type.
Similarly, a read buffer is contained within the BIU to buffer incoming data from main memory or another subsystem that is communicated on the external bus, until such time as the microprocessor is able to receive and process the data.
However, particularly for modern microprocessors for which the core clock is many times faster than the bus clock, synchronization circuitry and techniques for effecting data transfer through the read and write buffers, from one clock domain to another, has become a complex operation. This complexity is especially acute for synchronization of data traveling from the faster clock domain of the microprocessor to the slower clock domain of the external bus, through the write buffers. Conventional approaches to synchronization often impact the data path itself, and thus limit the performance of the microprocessor and the system. For example, synchronization may be effected by way of a two-way handshaking arrangement, in which a bit is set and cleared on both sides of the buffer (i.e., both the fast clock side and the slow clock side) to indicate the validity of a transaction. The speed of the data transfer is, of course, directly affected by such a technique.
Optimization of the size of write and read buffers is also a difficult problem for modern microprocessors. While large buffers are useful in connection with large memory access transactions, the use of large buffers can become inefficient when performing smaller transfers (i.e., a small amount of data to transfer can occupy a large buffer, precluding its use for other transactions).